import numpy as np
import os
import cv2


def get_class_names(file_path):
    """
        获取标签名称
    :param file_path:
    :return: 返回 对象
    """
    assert os.path.exists(file_path),'cannot find {}'.format(file_path)
    names = {}
    with open(file_path, 'r') as data:
        for ID, name in enumerate(data):
            names[ID] = name.strip('\n')
    return names

def get_anchors(file_path):
    """
        获取锚框
    :param file_path:
    :return: 返回 3 * 3 * 2  表示三种不同的尺寸大小下三种不同比例尺的长宽
    """
    assert os.path.exists(file_path), 'cannot find {}'.format(file_path)
    with open(file_path,'r') as f:
        anchors = f.readline()
    anchors = np.array(anchors.split(','), dtype=np.float32)
    return anchors.reshape(3, 3, 2)


def image_preprocess(orig_image, target_size, gt_box):
    """
        原始图片的缩放，box坐标随之也缩放
    :param orig_image:
    :param target_size:
    :param gt_box:
    :return: 缩放后的图片，缩放后图片对应的box
    """

    # 通道转化
    image = cv2.cvtColor(orig_image, cv2.COLOR_BGR2RGB).astype(np.float32)

    # 构造目标图片
    target_h, target_w = target_size
    image_target = np.full(shape=(target_h, target_w, 3),fill_value=128.0)

    # 按比例缩放原始图片
    h, w, _ = image.shape
    scale = min(target_h/h, target_w/w)
    nh, nw = scale * h, scale * w
    image_resized = cv2.resize(image, (nw, nh))

    # 将缩放后的图片粘贴到目标图片的中间位置
    dw, dh = (target_w - nw) / 2, (target_h - nh)/2
    image_target[dh:nh+dh, dw:nw+dw, :] = image_resized
    image_target = image_target / 255.0

    if gt_box is None:
        return image_target
    else:
        gt_box[:, [0, 2]] = gt_box[:, [0, 2]] * scale + dw
        gt_box[:, [1, 3]] = gt_box[:, [1, 3]] * scale + dh
        return image_target, gt_box


def bbox_iou(bbox1, bbox2):
    """
        生成两个bbox的 iou
    :param bbox1:(a,b,...,4)
    :param bbox2:(A,B,...,4)
    :return:返回iou (max(a,A),max(b,B),...) 如(1,4)和(3,4)--->(3,)
    """
    bbox1 = np.array(bbox1)
    bbox2 = np.array(bbox2)

    # 分别求两个框的面积
    bbox1_area = bbox1[..., 2] * bbox1[..., 3]
    bbox2_area = bbox2[..., 2] * bbox2[..., 3]

    # 分别计算两个框的左上，和右下两个顶点的坐标
    bbox1_xyxy = np.concatenate([
        bbox1[..., 0:2] - bbox1[..., 2:] * 0.5,
        bbox1[..., 0:2] + bbox1[..., 2:] * 0.5
    ], axis=-1)

    bbox2_xyxy = np.concatenate([
        bbox2[..., 0:2] - bbox2[..., 2:] * 0.5,
        bbox2[..., 0:2] + bbox2[..., 2:] * 0.5
    ], axis=-1)

    # 分别求三个anchor宽和真实框的交集面积
    max_left_up = np.maximum(bbox1_xyxy[..., 0:2], bbox2_xyxy[..., 0:2])
    min_right_down = np.minimum(bbox1_xyxy[..., 2:], bbox2_xyxy[..., 2:])

    intersection = np.maximum(min_right_down - max_left_up, 0.0)
    intersection_area = intersection[..., 0] * intersection[..., 1]

    # 求并集
    union_area = bbox1_area + bbox2_area - intersection

    # 求iou
    iou = intersection_area / (union_area + 1e-7)
    return iou